package padrao;

import geradores.GeradorCodigoObjetoAnalisadorSintatico;
import geradores.GeradorCodigoObjetoAnalisadorLexico;
import geradores.GeradorCodigoObjetoClasse;
import geradores.GeradorCodigoObjetoMain;
import geradores.GeradorCodigoObjetoTabela;
import geradores.GeradorCodigoObjetoToken;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Logger;

import util.ArquivoUtil;
import analisadorLexico.AnalisadorLexico;
import analisadorSemantico.AnalisadorSemantico;
import analisadorSintatico.AnalisadorSintatico;

/**
 * @author Alan L Cardoso
 * 
 */
public class Main {

	private static String caminhoArquivoGramatica = "c:\\gerador\\entrada\\gramatica.comp";

	private static String caminhoArquivoInfoGramatica = "c:\\gerador\\entrada\\classificacao.comp";

	private static String caminhoArquivoLog = "c:\\gerador\\";

	private static String nomeArquivoLog = "log.txt";

	private static PrintWriter arquivoLog;

	private final static Logger log = Logger.getLogger(Main.class.getName());

	public static void main(String[] args) throws IOException {

		arquivoLog = ArquivoUtil.criarArquivo(caminhoArquivoLog, nomeArquivoLog);
		validarArquivos();
		lerArquivo(caminhoArquivoGramatica);

	}

	private static void validarArquivos() throws FileNotFoundException {

		escreverArquivoLog("Verificando à Existência do Arquivo \"arquivo.comp\" no Diretório \"c:\\entrada\"..\n");
		if (!ArquivoUtil.validarArquivo(caminhoArquivoGramatica)) {
			escreverArquivoLog("Arquivo da Gramática não encontrado !");
			System.exit(0);
		}
		escreverArquivoLog("Arquivo \"arquivo.comp\" Encontrado com Sucesso !\n\n");

		escreverArquivoLog("Verificando à Existência do Arquivo \"classificacao.comp\" no Diretório \"c:\\entrada\"..\n");
		if (!ArquivoUtil.validarArquivo(caminhoArquivoInfoGramatica)) {
			escreverArquivoLog("Arquivo de Classificação Gramática não encontrado !");
			System.exit(0);
		}
		escreverArquivoLog("Arquivo \"classificacao.comp\" Encontrado com Sucesso !\n\n");

	}

	/**
	 * Método para iniciar a leitura do arquivo
	 * 
	 * @param caminhoArquivoGramatica
	 * @throws IOException
	 *             caso não consiga ler o arquivo
	 */

	private static void lerArquivo(String caminhoArquivoGramatica) throws IOException {

		BufferedReader regrasGramaticas = new BufferedReader(new FileReader(caminhoArquivoGramatica));

		/*
		 * Fases de Análise
		 */
		escreverArquivoLog("Iniciando Análise Léxica..\n");

		AnalisadorLexico analisadorLexico = new AnalisadorLexico(regrasGramaticas);
		analisadorLexico.analisar(caminhoArquivoLog, arquivoLog);

		escreverArquivoLog("Análise Léxica Realizada Com Sucesso !\n\n");

		escreverArquivoLog("Iniciando Análise Sintática..\n");

		AnalisadorSintatico analisadorSintatico = new AnalisadorSintatico(analisadorLexico.getTokens());
		analisadorSintatico.analisar(caminhoArquivoLog, arquivoLog);

		escreverArquivoLog("Análise Sintática Realziada Com Sucesso !\n\n");

		escreverArquivoLog("Iniciando Análise Semântica..\n");

		AnalisadorSemantico gramatica = new AnalisadorSemantico(analisadorSintatico.getRaiz());
		gramatica.analisar(caminhoArquivoLog, arquivoLog);
		gramatica.verificarRegras(arquivoLog);

		escreverArquivoLog("Análise Semântica Concluída Com Sucesso !\n\n");

		/*
		 * Fases de Construção
		 */

		log.info("Iniciando Construção da Classe \"AnalisadorLexico.java\"..");
		escreverArquivoLog("Iniciando Construção da Classe \"AnalisadorLexico.java\"..\n");

		BufferedReader classificacaoToken = new BufferedReader(new FileReader(caminhoArquivoInfoGramatica));
		GeradorCodigoObjetoAnalisadorLexico geradorAnalisadorLexico = new GeradorCodigoObjetoAnalisadorLexico(
				classificacaoToken, AnalisadorSemantico.getTerminalClasse());
		geradorAnalisadorLexico.gerarAnalisadorLexico();

		log.info("\"AnalisadorLexico.java\" Gerado Com Sucesso !");
		escreverArquivoLog("\"AnalisadorLexico.java\" Gerado Com Sucesso !\n\n");

		log.info("Iniciando Construção da Classe \"Token.java\"..");
		escreverArquivoLog("Iniciando Construção da Classe \"Token.java\"..\n");

		GeradorCodigoObjetoToken geradorClassToken = new GeradorCodigoObjetoToken();
		geradorClassToken.gerar();

		log.info("\"Token.java\" Gerada Com Sucesso !");
		escreverArquivoLog("\"Token.java\" Gerado Com Sucesso !\n\n");

		log.info("Iniciando Construção da Classe \"Classe.java\"..");
		escreverArquivoLog("Iniciando Construção da Classe \"Classe.java\"..\n");

		GeradorCodigoObjetoClasse geradorClassClasse = new GeradorCodigoObjetoClasse(
				geradorAnalisadorLexico.getRegrasInfo());

		geradorClassClasse.gerar();

		log.info("\"Classe.java\" Gerada Com Sucesso !");
		escreverArquivoLog("\"Classe.java\" Gerado Com Sucesso !\n\n");

		log.info("Iniciando Construção da Classe \"Tabela.java\"..");
		escreverArquivoLog("Iniciando Construção da Classe \"Tabela.java\"..\n");

		GeradorCodigoObjetoTabela geradorClasseTabela = new GeradorCodigoObjetoTabela(
				AnalisadorSemantico.getTerminalLiteral());
		geradorClasseTabela.gerar();

		log.info("\"Tabela.java\" Gerada Com Sucesso !");
		escreverArquivoLog("\"Tabela.java\" Gerado Com Sucesso !\n\n");

		log.info("Iniciando Construção da Classe \"Main.java\"..");
		escreverArquivoLog("Iniciando Construção da Classe \"Main.java\"..\n");

		GeradorCodigoObjetoMain geradorClasseMain = new GeradorCodigoObjetoMain();
		geradorClasseMain.gerar();

		log.info("\"Main.java\" Gerada Com Sucesso !");
		escreverArquivoLog("\"Main.java\" Gerado Com Sucesso !\n\n");

		log.info("Iniciando Construção da Classe \"AnalisadorSintatico.java\"..");
		escreverArquivoLog("Iniciando Construção da Classe \"AnalisadorSintatico.java\"..\n");

		GeradorCodigoObjetoAnalisadorSintatico geradorAnalisadorSintatico = new GeradorCodigoObjetoAnalisadorSintatico(
				AnalisadorSemantico.getRegras());

		geradorAnalisadorSintatico.gerar();

		log.info("\"AnalisadorSintatico.java\" Gerada Com Sucesso !");
		escreverArquivoLog("\"AnalisadorSintatico.java\" Gerado Com Sucesso !\n\n");

		ArquivoUtil.fecharArquivo(arquivoLog);

	}

	private static void escreverArquivoLog(String mensagem) {
		ArquivoUtil.escreverArquivo(mensagem, arquivoLog);
	}
}
